![]() Acrobat file (227K) |
![]() ClarisWorks 4 file (44K) |
![]() QuickView file (284K) |
Technote 1025 | FEBRUARY 1996 |
This Technote describes a workaround to a bug in the first version of the Driver Loader Library in System 7.5.2 and System Update 7.5.3. (The bug should be fixed in later versions of the Mac OS.) As of this writing, the Driver Loader Library is only available on Power Macintoshes that support PCI cards (for example:Power Mac 7200, 7500, 8500 and 9500). There is a bug in the routine GetDriverInformation that can possibly cause an overwriting past the end of the name string that is passed in.
This Technote is directed primarily at writers or family experts and especially
applications that get information about drivers.
Contents
This bug surfaces only when calling GetDriverInformation() for a driver that has had its Device Control Entry fields zeroed when it was closed (the Chooser driver has been observed to exhibit this behavior). The bug occurs because GetDriverInformation() does not check for zeroed fields before using the dCtlDriver field to reference the driver's name; instead, it copies a garbage string from low memory into the name string passed as a parameter to GetDriverInformation().
If the first byte of this garbage string is larger than the number bytes of storage allocated by the caller for the name string, then the caller's data located just past the end of name's storage will be overwritten with garbage.
You can see the zeroing out of fields for the Chooser's driver by following these steps using any version of MacsBug:
1. Open the Chooser.
2. Drop into MacsBug and type:
drvr <return>3. Look down the list of drivers in the Driver column of the drvr display and see the Chooser (on my machine it's at dNum 0xF).
dm xxxxx dctlentry <return>(where xxxxx is the hexidecimal number in the Chooser's row in the "DCE at"column in the drvr display)
4. Exit Macsbug by hitting Command-g.
5. Close the Chooser window.
6. Drop into MacsBug and type:
drvr <return>You'll see that name Chooser is replace by blanks in the row that it was in.
7. To see the zeroing of DCE fields type:
dm xxxxx dctlentry <return>(again, where xxxxx is the hexidecimal number in the Chooser's row in the "DCE at" column in the drvr display).
You'll see that all fields except the RefNum field have been zeroed.
It's doubtful that any expert code will encounter this problem if the expert code executes pre-Finder; applications that execute after the Finder boots are the most likely victims. If your code calls GetDriverInformation() after a user has a chance to close one of these "zeroed-out" drivers (and the DCE fields are thus zeroed), then you will need this workaround. If you call GetDriverInformation only for a driver that you know doesn't have its Device Control Entry fields zeroed upon closing, then you don't need this workaround because the bug will not appear. It is only when you traverse the unit table, calling GetDriverInformation for unknown drivers, that you need to be aware of the workaround.
extern OSErr GetDriverInformation (DriverRefNum refNum, UnitNumber *unitNum, DriverFlags *flags, DriverOpenCount *count, StringPtr name, // ** this is the field we are concerned with// RegEntryID *device, CFragHFSLocator *driverLoadLocation, CFragConnectionID *fragmentConnID, DriverEntryPointPtr *fragmentMain, DriverDescription *driverDesc);It is the StringPtr name parameter that we are concerned with. If you allocate, for example, a Str31 to use to pass in as the StringPtr, then (if the erroneous byte GetDriverInformation thinks is the length byte of the garbage string is greater than 0x1f, or 31 decimal) GetDriverInformation will unwittingly copy all the garbage bytes to your code without regard to the actual location of the end of the name string.
void TraverseDrivers() { OSErr err = noErr; DriverRefNum refNum; UnitNumber unitNum; DriverFlags flags; DriverOpenCount count; RegEntryID device; CFragHFSLocator driverLoadLocation; DriverDescription driverDesc; // Str63 theName; // BAD, not long enough Str255 theName; // GOOD:THIS IS THE WORKAROUND! FSSpec loadLocSpec; short i; // this is another caveat about using GetDriverInformation(); you must // initialize the FSSpec ptr field of the driverLoadLocation struct to // point to an allocated FSSpec because GetDriverInformation assumes you // have. This is done is the next line below. driverLoadLocation.u.onDisk.fileSpec = &loadLocSpec; for( i = 0; i <= HighestUnitNumber(); ++i ){ refNum = ~i; // convert the unit number to a driver refNum. err = GetDriverInformation( refNum, &unitNum, &flags, &count, theName, &device, &driverLoadLocation, &fragmentConnID, &fragmentMain, &driverDesc); if( err != noErr ){ // there's a driver for this refNum // Do whatever it was you wanted to do with the information // BEWARE: If the driver is a non-native driver, that is a // 68k driver of pre-PCI-supporting Macintosh, the device, // driverLoadLocation, fragmentConnID, fragmentMain, and // driverDesc inputs above will be set to nil after the call // because these fields don't apply to 68k drivers. } } // for } // end TraverseDrivers()
OSErr GetDriverInformation (DriverRefNum refNum, UnitNumber *unitNum, DriverFlags *flags, DriverOpenCount *count, StringPtr name, RegEntryID *device, CFragHFSLocator *driverLoadLocation, CFragConnectionID *fragmentConnID, DriverEntryPointPtr *fragmentMain, DriverDescription *driverDesc);
refNum refNum of driver to examine unit resulting unit number flags resulting DCE flag bits count number of times driver has been opened name resulting driver name device resulting Name Registry device specification driverLocation resulting CFM fragment locator (from which the driver was loaded) fragmentConnID resulting CFM connection ID fragmentMain resulting pointer to DoDriverIO driverDesc resulting pointer to DriverDescription
DESCRIPTION
GetDriverInformation is used by driver experts in PCI-bus-supporting machines, software that makes decisions about which driver to load for a particular device -- or by any software that needs to get information about a driver for a device.Given the Unit Table reference number of an installed driver, GetDriverInformation returns the driver's unit number in unit, its DCE flags in flags, the number of times it has been opened in count, its name in name, its RegEntryID value in device, its CFM fragment locator in driverLocation, its CFM connection ID in fragmentConnID, its DoDriverIO entry point in fragmentMain, and its Driver Description in driverDesc.
RESULT CODES
noErr 0 No error badUnitErr -21 Bad unit number unitEmptyErr -22 Empty unit number